package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.bean.Dish;
import com.itheima.bean.DishFlavor;
import com.itheima.bean.Setmeal;
import com.itheima.bean.SetmealDish;
import com.itheima.dao.DishDao;
import com.itheima.dao.DishFlavorDao;
import com.itheima.dto.DishDto;
import com.itheima.exception.CustomException;
import com.itheima.service.DishService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

@Service
public class DishServiceImpl extends ServiceImpl<DishDao, Dish> implements DishService {


    @Autowired
    private DishFlavorDao dishFlavorDao  ;



    @Override
    public void saveWithFlavor(DishDto dishDto) {

        //0.判断菜品名称是否存在  存在：抛出自定义异常提示
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Dish::getName,dishDto.getName());
        int count = this.count(wrapper);
        if(count>0){
            throw new CustomException("当前菜品【"+dishDto.getName()+"】已经存在！");
        }

        //1.保存菜品基本信息到菜品表    dish
        // 这里使用MyBatisPlus提供的service通用方法即可 dishDto是Dish子类对象  新增的时候插入数据到dish表 只会拿DishDto中继承Dish类的那些属性使用
        this.save(dishDto);

        //2.保存菜品口味信息到菜品口味表 dish_flavor
        //1.获取当前新增菜品口味列表数据   一个菜品下可以有多个口味设置
        List<DishFlavor> flavors = dishDto.getFlavors();

        //2.遍历当前菜品口味信息列表数据  设置每条口味信息关联当前新增菜品id  保存到dish_flavor表中
        //a：获取当前新增菜品id   原因：因为前面已经将菜品基本信息保存到菜品dish表中 MyBatisPlus中保存数据时会自动返回主键数据封装到原有对象属性中
        Long dishId = dishDto.getId();

        /*
            回顾lambda表达式：
                书写格式：()->{}
                    ()中放方法参数   也就是Stream流中的元素   {}:方法体 重新抽象方法
                省略规则:
                    1.小括号中如果只有一个参数 可以省略小括号
                    2.大括号中如果只有一句代码 这可以省略大括号以及return
         */
        //高级玩法：Stream流 高大上
        //b.遍历当前菜品口味信息列表数据   这里不需要非空判断
        flavors.stream().forEach((flavor)->{
            //c：设置每条口味信息关联当前新增菜品id
            flavor.setDishId(dishId);

            //d：保存到dish_flavor表中
            dishFlavorDao.insert(flavor);
        });

        /* for循环遍历数据   low
        //b.遍历当前菜品口味信息列表数据
        if(flavors!=null && flavors.size()>0){
            for (DishFlavor flavor : flavors) {
                //c：设置每条口味信息关联当前新增菜品id
                flavor.setDishId(dishId);

                //d：保存到dish_flavor表中
                dishFlavorDao.insert(flavor);
            }
        }
        */

    }

    @Override
    public DishDto findById(Long id) {
        DishDto dishDto = new DishDto();

        //1.根据菜品id去菜品dish表中查询菜品基本信息封装到DishDto对象中
        /*
            this表示当前类对象
                this.getById()：调用当前类中的非静态方法
                    getById方法是由MyBatisPlus在IService中提供的通用方法 已经封装好的 因为我们的Service实现类继承了ServiceImpl实现了IService
                    this在使用时 可以省略
         */
        Dish dish = this.getById(id);
        BeanUtils.copyProperties(dish,dishDto);

        //2.根据菜品id去菜品口味表中查询菜品口味信息封装到DishDto对象中
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DishFlavor::getDishId,id);
        List<DishFlavor> flavors = dishFlavorDao.selectList(wrapper);
        dishDto.setFlavors(flavors);

        //3.返回DishDto
        return dishDto;
    }

    @Override
    public void updateWithFlavor(DishDto dishDto) {
        //1.判断修改后的菜品名称和dish表中其他的菜品名称不重复
        LambdaQueryWrapper<Dish> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(Dish::getName,dishDto.getName());
        wrapper1.ne(Dish::getId,dishDto.getId());       //不是自己
        int count = this.count(wrapper1);
        if(count>0){
            throw new CustomException("当前菜品名称【"+dishDto.getName()+"】已经存在！");
        }

        //2.将修改后的菜品基本信息保存到菜品表dish中
        this.updateById(dishDto);

        //3.删除当前菜品原有的口味信息  根据菜品id去菜品口味dish_flavor表中删除
        //获取当前菜品id
        Long dishId = dishDto.getId();
        LambdaQueryWrapper<DishFlavor> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.eq(DishFlavor::getDishId,dishId);
        dishFlavorDao.delete(wrapper2);     // delete from dish_flavor where dish_id = xxx

        //4.将修改后的菜品口味信息保存到菜品口味表dish_flavor中，关联菜品id
        //a.获取当前菜品修改后的口味信息列表
        List<DishFlavor> flavors = dishDto.getFlavors();

        //b.遍历当前菜品口味信息列表数据   这里不需要非空判断
        flavors.stream().forEach((flavor)->{
            /*
                如果前面是使用物理删除，则可以不需要设置为null 原因是我们下面执行的是insert新增 不能插入两条数据使用相同的id
                当使用逻辑删除时 就必须设置新插入的菜品口味信息id为null  否则会报主键重复异常
             */
            //c1：设置每条口味信息的id为null
            flavor.setId(null);

            //c2：设置每条口味信息关联当前修改菜品id
            flavor.setDishId(dishId);

            //d：保存到dish_flavor表中
            dishFlavorDao.insert(flavor);
        });
    }

    //删除
    @Override
    public void deleteByIds(Long[] ids) {
        //0.判断ids是否为null 或长度为0
        if(ids==null || ids.length==0){
            throw new CustomException("请选择要删除的套餐！！！");
        }

        //1.判断要删除是否停售 没有：抛出异常提示
        List<Dish> dishList = this.getBaseMapper().selectBatchIds(Arrays.asList(ids));
        for (Dish dish : dishList) {
            if(dish.getStatus()==1){
                throw new CustomException("当前套餐【"+dish.getName()+"】处于启售状态，不能删除！！！");
            }
        }

        //2.根据id删除基本信息数据
        this.removeByIds(Arrays.asList(ids));

    }





}

